﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Autofac;
using ComputerVision.ANN;
using ComputerVision.BaseForm;
using ComputerVision.Common;
using ComputerVision.Data;
using ComputerVision.Services;
using System;
using System.Drawing;
using RawInput_dll;
using SimpleLPR2;

namespace ComputerVision
{
    public partial class frmXeRaNew : frmObject
    {
        private IService<ConfigrationCamera> _configCamera;
        private IService<LoaiXe> _loaiXe;
        private IService<VeXe> _veXe;
        private IService<XeTemp> _xeT;
        private IService<Xe> _xe;
        private VeXe _veXe2;
        private XeTemp _xe3;
        private XeTemp _xe4;
        private Xe _model = null;
        private string _veTemp = string.Empty;

        private string _computerName;
        string bienso;
        private System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex("\\d\\d-[A-Z][0-9A-Z]-\\d{4,5}");
        private System.Text.RegularExpressions.Regex regexoto = new System.Text.RegularExpressions.Regex("\\d\\d-[A-Z]-\\d{4,5}");
        //private string _soVe;

        private Bitmap imgT = null;
        private Bitmap imgS = null;

        private readonly RawInput _rawinput;
        private string cardNumber = string.Empty;
        private bool isCardReaderRa = false;
        private bool isCardReaderVao = false;
        private bool readOk = false;
        private string tempNumber = string.Empty;
        private string readerDevideVao = string.Empty;
        private string readerDevideRa = string.Empty;

        private string tempFile = string.Empty;
        private ImgageArrayRa imageArray;
        private FileUtil fileUtil;
        private int countT = 0;
        private int countS = 0;
        private string cardStatus = string.Empty;
        private string oldCard = string.Empty;
        private bool isValidCard = true;

        //private bool wroteImage1 = false;
        //private bool wroteImage2 = false;
        private int autoCount = 0;

        ISimpleLPR lpr;
        private IProcessor proc;
        List<Candidate> cds;

        #region Handle methods

        public frmXeRaNew()
        {
            InitializeComponent();

            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            _rawinput = new RawInput(Handle);
            _rawinput.CaptureOnlyIfTopMostWindow = true;    // Otherwise default behavior is to capture always
            _rawinput.AddMessageFilter();                   // Adding a message filter will cause keypresses to be handled
            _rawinput.KeyPressed += OnKeyPressed;

            _computerName = Environment.MachineName;
            _configCamera = Program.Container.Resolve<IService<ConfigrationCamera>>();
            _loaiXe = Program.Container.Resolve<IService<LoaiXe>>();
            _xeT = Program.Container.Resolve<IService<XeTemp>>();
            _xe = Program.Container.Resolve<IService<Xe>>();
            _veXe = Program.Container.Resolve<IService<VeXe>>();
            //_process = new ImageProcess();
            //_soVe = txtSoVe.Text;
            LoadLoaiXe();
            fileUtil = new FileUtil();
            lpr = SimpleLPR.Setup();
            //read license
            lpr.set_countryWeight("Vietnam", 1.0f);
            lpr.realizeCountryWeights();
            proc = lpr.createProcessor();

            axLiveSau.OnGetPicture += new AxLIVEXLib._DLiveXEvents_OnGetPictureEventHandler(axLiveSau_OnGetPicture);
            axLiveTruoc.OnGetPicture += new AxLIVEXLib._DLiveXEvents_OnGetPictureEventHandler(axLiveTruoc_OnGetPicture);
        }

        void axLiveSau_OnGetPicture(object sender, AxLIVEXLib._DLiveXEvents_OnGetPictureEvent e)
        {
            if (countS == 1)
            {
                return;
            }
            axLiveSau.StartGrapImage(false);
            imgS = ImageProcess.ImageConvert.GetImageFromIPicture(e.mPict);

            //img3end = imgS;
            imgRaSau.Image = imgS;
            countS = 1;

            if (fileUtil.WriteImage(imgRaSau.Image, imageArray.NameSau, "R"))
            {
                //wroteImage2 = true;

                if (cardStatus == string.Empty)
                {
                    _model = new Xe()
                    {
                        Id = Guid.NewGuid(),
                        LoaiXeId = _xe3.LoaiXeId,
                        SoVe = _xe3.SoVe,
                        BienSoXe = _xe3.BienSoXe,
                        NgayVao = _xe3.NgayVao,
                        NgayRa = DateTime.Now,
                        GiaTien = _xe3.GiaTien,
                        ImgBienXeVao = _xe3.ImgBienXeVao,
                        ImgVaoTruoc = _xe3.ImgVaoTruoc,
                        ImgVaoSau = _xe3.ImgVaoSau,
                        //ImgBienXeRa = this.imageArray.NameBienSoUrl,
                        ImgRaTruoc = this.imageArray.NameTruocUrl,
                        ImgRaSau = this.imageArray.NameSauUrl,
                        Status = _xe3.Status,
                        Created = _xe3.Created,
                        CreatedBy = _xe3.CreatedBy,
                        Modified = DateTime.Now,
                        ModifiedBy = Constants.CurrentUser
                    };
                }

            }
            else
            {
                //wroteImage2 = false;
                AlertList.Error("Không ghi được ảnh chụp từ camera sau. Vui lòng thử lại...");
            }

            //Timer_Ra.Enabled = true;
            if (imgRaSau.Image != null)
            {
                cds = proc.analyze((Bitmap)imgRaSau.Image, 120);
                if (cds.Count > 0)
                {
                    foreach (Candidate cd in cds)
                    {
                        txtBiensora.Text = cd.text;
                    }
                }
                else
                    txtBiensora.Text = "";
            }
            autoCount = 0;
        }

        void axLiveTruoc_OnGetPicture(object sender, AxLIVEXLib._DLiveXEvents_OnGetPictureEvent e)
        {
            if (countT == 1)
            {
                return;
            }
            axLiveSau.StartGrapImage(true);
            countS = 0;
            this.imageArray = new ImgageArrayRa(tempFile, fileUtil.tempFolderToday);

            axLiveTruoc.StartGrapImage(false);
            imgT = ImageProcess.ImageConvert.GetImageFromIPicture(e.mPict);

            // img2end = imgT;
            imgRaTruoc.Image = imgT;
            countT = 1;

            if (!fileUtil.WriteImage(imgRaTruoc.Image, imageArray.NameTruoc, "R"))
            {
                AlertList.Error("Không ghi được ảnh chụp từ camera trước. Vui lòng thử lại.");
            }
        }

        private void frmXeRa_Load(object sender, System.EventArgs e)
        {
            //CaptureWC();
            foreach (LoaiXe loaiXe in cbLoaixe.Items)
            {
                if (loaiXe.Ten.ToUpper().Equals(Constants.Xe.XeMay.ToUpper()))
                {
                    cbLoaixe.SelectedItem = loaiXe;
                    break;
                }
            }

            //Save();

            var item = _configCamera.ToList().ToList().FirstOrDefault(p => p.ComputerName.Contains(_computerName));
            if (item != null)
            {
                int pos = item.CardReader.IndexOf('|');
                if (pos < 0 || (item.CardReader[pos + 1] != '|' && item.CardReader[pos + 2] != '|'))
                    AlertList.Information("Không xác định được thiết bị đọc thẻ. Vui lòng thiết lập cài đặt.");
                else
                {
                    readerDevideVao = item.CardReader.Substring(0, pos);
                    readerDevideRa = item.CardReader.Substring(pos + 3);
                }

                this.axLiveTruoc.IpAddress = item.Server;
                this.axLiveTruoc.CommandPort = System.Convert.ToInt32("4550");
                this.axLiveTruoc.DataPort = System.Convert.ToInt32("5550");
                this.axLiveTruoc.AudioDataPort = System.Convert.ToInt32("6550");
                this.axLiveTruoc.DisablePWD = true;
                this.axLiveTruoc.DefaultCam = short.Parse(item.Cam3.ToString()); ;
                this.axLiveTruoc.UserName = item.UserID;
                this.axLiveTruoc.Password = item.Password;
                this.axLiveTruoc.PlayX();

                this.axLiveSau.IpAddress = item.Server;
                this.axLiveSau.CommandPort = System.Convert.ToInt32("4550");
                this.axLiveSau.DataPort = System.Convert.ToInt32("5550");
                this.axLiveSau.AudioDataPort = System.Convert.ToInt32("6550");
                this.axLiveSau.DisablePWD = true;
                this.axLiveSau.DefaultCam = short.Parse(item.Cam4.ToString());
                this.axLiveSau.UserName = item.UserID;
                this.axLiveSau.Password = item.Password;
                this.axLiveSau.PlayX();
            }
            else
            {
                AlertList.Warning("Bạn phải thiết lập camera và thiết bị đọc thẻ cho hệ thống trước khi sử dụng.");
            }
        }

        private void TiepTuc()
        {
            if (_model != null)
            {
                Edit();
                _model = null;
            }
            else
            {
                AlertList.Error("Lỗi phát sinh khi thêm dữ liệu.");
            }
            txtSoVe.Focus();
        }

        private void timerClock_Tick(object sender, EventArgs e)
        {
            GC.Collect();

            if (autoCount == 100)
            {
                if (_model != null)
                {
                    //btnTiep.PerformClick();
                    TiepTuc();
                }
                _veTemp = cardNumber;
                autoCount = 0;
            }
            else
            {
                autoCount++;
            }
        }

        private void txtSoVe_MouseEnter(object sender, EventArgs e)
        {
            txtSoVe.SelectAll();
        }

        private void txtSoVe_MouseDown(object sender, MouseEventArgs e)
        {
            txtSoVe.SelectAll();

        }

        private void frmXeRa_FormClosed(object sender, FormClosedEventArgs e)
        {
            _rawinput.KeyPressed -= OnKeyPressed;
            GC.Collect();
        }

        private void frmXeRa_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (isCardReaderRa)
            {
                ReadFromCardReader(e);
                if (readOk)
                {
                    cardStatus = string.Empty;
                    txtSoVe.Text = cardNumber;

                    axLiveTruoc.StartGrapImage(true);
                    countT = 0;

                    tempFile = DateTime.Now.ToString("yyyyMMddHHmmssffff") + "_" + _computerName;

                    if (ValidCard() && _xe3 != null)
                    {
                        txtBienSoVao.Text = _xe3.BienSoXe;
                        lblThoaiGianvao.Text = ((_xe3.NgayVao.HasValue) ? _xe3.NgayVao.Value.ToString("HH:mm:ss tt dd/MM/yyyy") : "");

                        foreach (LoaiXe itemx in cbLoaixe.Items)
                        {
                            if (itemx.Id == _xe3.LoaiXe.Id)
                            {
                                cbLoaixe.SelectedItem = itemx;
                                break;
                            }

                        }

                        try
                        {
                            imgVaoTruoc.Load(fileUtil.GenerateLink("ANHVAO", _xe3.ImgVaoTruoc));

                        }
                        catch (Exception)
                        {
                            //MessageBox.Show(ex.Message);
                            imgVaoTruoc.Image = null;
                        }

                        try
                        {
                            imgVaoSau.Load(fileUtil.GenerateLink("ANHVAO", _xe3.ImgVaoSau));

                        }
                        catch (Exception)
                        {
                            //MessageBox.Show(ex.Message);
                            imgVaoSau.Image = null;
                        }

                    }
                    else
                    {
                        txtBienSoVao.Text = "";
                        lblThoaiGianvao.Text = "";
                        imgVaoTruoc.Image = null;
                        imgVaoSau.Image = null;
                    }


                    if (_model != null && _veTemp != cardNumber)
                    {
                        TiepTuc();
                    }
                    _veTemp = cardNumber;
                    oldCard = txtSoVe.Text.Trim();

                    txtBiensora.Focus();
                    txtBiensora.SelectAll();
                    autoCount = 0;
                }
            }

            GC.Collect();
        }

        private void frmXeRa_KeyDown(object sender, KeyEventArgs e)
        {
            if (!isCardReaderRa && !isCardReaderVao)
            {
                if (e.KeyCode == Keys.F2)
                {
                    //btnDocLai.PerformClick();
                }
                else if (e.KeyCode == Keys.Enter)
                {
                    if (!txtSoVe.Focused && cardStatus.Equals(string.Empty))
                    {
                        //btnTiep.PerformClick();
                        //btnDocLai.PerformClick();
                        TiepTuc();
                    }
                    else if (!txtSoVe.Focused && !cardStatus.Equals(string.Empty))
                    {
                        AlertList.Error(cardStatus);
                    }
                }
                else if (e.KeyCode == Keys.F1)
                {
                    cardNumber = string.Empty;
                    txtSoVe.Text = string.Empty;
                    txtSoVe.Focus();
                    cbLoaixe.SelectedItem = cbLoaixe.Items[1];

                }
                else if (e.KeyCode == Keys.F3)
                {
                    cbLoaixe.SelectedItem = cbLoaixe.Items[1];
                    cbLoaixe.SelectedItem = cbLoaixe.Items[0];
                    //txtSoVe.Text = string.Empty;
                    txtBiensora.Focus();
                }
            }
        }

        #endregion

        #region Private methods

        private void LoadLoaiXe()
        {
            var loaixe = _loaiXe.ToList().ToList();
            foreach (LoaiXe loai in loaixe)
            {
                cbLoaixe.Items.Add(loai);
            }
        }

        private static void CurrentDomain_UnhandledException(Object sender, UnhandledExceptionEventArgs e)
        {
            var ex = e.ExceptionObject as Exception;

            if (null == ex) return;

            // Log this error. Logging the exception doesn't correct the problem but at least now
            // you may have more insight as to why the exception is being thrown.
            //Debug.WriteLine("Unhandled Exception: " + ex.Message);
            //Debug.WriteLine("Unhandled Exception: " + ex);
            MessageBox.Show(ex.Message);
        }

        private void OnKeyPressed(object sender, InputEventArg e)
        {
            if (e.KeyPressEvent.DeviceName.Equals(readerDevideRa))
            {
                isCardReaderRa = true;
                txtBiensora.ReadOnly = true;
                isCardReaderVao = false;

            }
            else if (e.KeyPressEvent.DeviceName.Equals(readerDevideVao))
            {
                txtBiensora.ReadOnly = true;
                isCardReaderVao = true;
                isCardReaderRa = false;

            }
            else
            {
                isCardReaderRa = false;
                isCardReaderVao = false;
                txtBiensora.ReadOnly = false;
            }
        }

        private void ReadFromCardReader(KeyPressEventArgs e)
        {
            if (e.KeyChar != 13)
            {
                tempNumber = tempNumber + e.KeyChar;
                readOk = false;
                e.Handled = true;
            }
            else
            {
                cardNumber = tempNumber;
                tempNumber = string.Empty;
                readOk = true;

            }
        }

        #region Validation

        private bool ValidCard()
        {
            isValidCard = true;
            _veXe = Program.Container.Resolve<IService<VeXe>>();
            _xeT = Program.Container.Resolve<IService<XeTemp>>();

            _veXe2 = _veXe.Detail(txtSoVe.Text.Trim());
            _xe3 = _xeT.GetByMaxValue("SoVe", "NgayVao", "XeTemp", txtSoVe.Text.Trim());

            if (txtSoVe.Text.Trim().Equals(string.Empty))
            {
                lblTrangThaiThe.Text = @"Đang chờ";
                lblTrangThaiThe.ForeColor = Color.Black;
                isValidCard = false;
            }

            else if (_veXe2 == null)
            {
                lblTrangThaiThe.Text = Constants.VeMessages.VeKhongCoTrongDuLieu;
                cardStatus = Constants.VeMessages.VeKhongCoTrongDuLieu;
                lblTrangThaiThe.ForeColor = Color.Red;
                isValidCard = false;
                _xe3 = null;
                AlertList.Error(cardStatus);
            }

            else if (_veXe2.Status.Equals(Constants.StatusVeXe.MatVe))
            {
                lblTrangThaiThe.Text = Constants.VeMessages.MatVe;
                cardStatus = Constants.VeMessages.MatVe;
                lblTrangThaiThe.ForeColor = Color.Red;
                isValidCard = false;
                _xe3 = null;
                AlertList.Error(cardStatus);
            }

            else if (_veXe2.Status.Equals(Constants.StatusVeXe.InActive))
            {
                lblTrangThaiThe.Text = Constants.VeMessages.VeKhongHoatDong;
                cardStatus = Constants.VeMessages.VeKhongHoatDong;
                lblTrangThaiThe.ForeColor = Color.Red;
                _xe3 = null;
                isValidCard = false;
                AlertList.Error(cardStatus);
            }

            //_xe2 = _xe.ToList().ToList()
            //                .OrderByDescending(b => b.NgayVao)
            //                .FirstOrDefault(p => p.SoVe.Equals(txtSoVe.Text.Trim()));

            else if (_xe3 == null || (_xe3.NgayRa != null && _xe3.ImgRaTruoc != null && _xe3.ImgRaSau != null))
            {
                lblTrangThaiThe.Text = Constants.VeMessages.VeChuaVao;
                cardStatus = Constants.VeMessages.VeChuaVao;
                lblTrangThaiThe.ForeColor = Color.Red;
                _xe3 = null;
                isValidCard = false;
                AlertList.Error(cardStatus);
            }

            else
            {
                lblTrangThaiThe.Text = Constants.VeMessages.VeHopLe;
                isValidCard = true;
                lblTrangThaiThe.ForeColor = Color.Blue;
            }
            //else
            //{
            //    lblTrangThaiThe.Text = @"";
            //}
            _veXe2 = null;

            return isValidCard;
        }

        #endregion

        #region Edit

        protected void Edit()
        {
            //_xe3 = _xeT.GetByMaxValue("SoVe", "NgayVao", "XeTemp", txtSoVe.Text.Trim());

            try
            {
                _xe.Create(_model);

                _xeT = Program.Container.Resolve<IService<XeTemp>>();
                _xe4 = _xeT.GetByMaxValue("SoVe", "NgayVao", "XeTemp", oldCard);
                _xeT.Delete(_xe4);

                //Reset controls
                cardStatus = string.Empty;
                txtSoVe.Focus();
            }
            catch (Exception)
            {
                AlertList.Error("Có lỗi khi xử lý dữ liệu.");
            }

        }

        #endregion

        #endregion

        #region Nhan dang bien so

        //private void CaptureWC()
        //{
        //    //_cmr2 = 0;
        //    cap2 = new Capture(_cmr3);
        //    cap2.ImageGrabbed += wc2;
        //    cap2.Start();

        //    //_cmr3 = 0;
        //    cap3 = new Capture(_cmr2);
        //    cap3.ImageGrabbed += wc1detectFace;
        //    cap3.Start();
        //}

        //private void wc1detectFace(object sender, EventArgs e)
        //{
        //    var faceDetector1 = new CascadeClassifier("haarcascade_frontalface_default.xml");
        //    img2 = cap3.RetrieveBgrFrame();
        //    imgGray2 = img2.Convert<Gray, byte>();
        //    foreach (var face in faceDetector1.DetectMultiScale(imgGray2, 1.1, 10, new Size(20, 20), Size.Empty))
        //    {
        //        img2.Draw(face, new Bgr(Color.White), 1);
        //    }
        //    //imgRaTruoc.Image = img2;
        //    //picRaTruoc.Image = img2.Bitmap;
        //}

        //private void wc2(object sender, EventArgs e)
        //{
        //    try
        //    {
        //        img3 = cap2.RetrieveBgrFrame();
        //        //imgRaSau.Image = img3;
        //        //picRaSau.Image = img3.Bitmap;
        //    }
        //    catch (Exception ex)
        //    {

        //    }
        //}




        //Neural Network Object With Output Type String
        //private NeuralNetwork<string> neuralNetwork = null;

        ////Data Members Required For Neural Network
        //private Dictionary<string, double[]> TrainingSet;
        //private int av_ImageHeight = 0;
        //private int av_ImageWidth = 0;
        //private int NumOfPatterns = 0;

        //private void Save()
        //{

        //    string[] Images = Directory.GetFiles(Application.StartupPath + @"\ImageTrainning", "*.bmp");
        //    NumOfPatterns = Images.Length;
        //    av_ImageHeight = 0;
        //    av_ImageWidth = 0;
        //    foreach (string s in Images)
        //    {
        //        var Temp = new Bitmap(s);
        //        av_ImageHeight += Temp.Height;
        //        av_ImageWidth += Temp.Width;
        //        Temp.Dispose();
        //    }
        //    av_ImageHeight /= NumOfPatterns;
        //    av_ImageWidth /= NumOfPatterns;

        //    int networkInput = av_ImageHeight * av_ImageWidth;
        //    GenerateTrainingSet();
        //    CreateNeuralNetwork();
        //}

        //private void CreateNeuralNetwork()
        //{
        //    if (TrainingSet == null)
        //        throw new Exception("Unable to Create Neural Network As There is No Data to Train..");

        //    neuralNetwork = new NeuralNetwork<string>
        //        (new BP3Layer<string>(av_ImageHeight * av_ImageWidth, 295, 98, NumOfPatterns), TrainingSet);

        //    neuralNetwork.MaximumError = 1.1;
        //    neuralNetwork.LoadNetwork(Application.StartupPath + @"\ImageTrainning\Model.net");
        //}

        //private void GenerateTrainingSet()
        //{
        //    // string[] Patterns = Directory.GetFiles(@"C:\Users\bienphongvnn\Desktop\hinhanhhuanluyen", "*.bmp");
        //    string[] Patterns = Directory.GetFiles(Application.StartupPath + @"\ImageTrainning", "*.bmp");
        //    TrainingSet = new Dictionary<string, double[]>(Patterns.Length);
        //    foreach (string s in Patterns)
        //    {
        //        var Temp = new Bitmap(s);
        //        TrainingSet.Add(Path.GetFileNameWithoutExtension(s),
        //            ImageProcessing.ToMatrix(Temp, av_ImageHeight, av_ImageWidth));
        //        Temp.Dispose();
        //    }


        //}

        #endregion

    }
}
